#include <memory>
#include <common/Logger.h>
#include "CommandBase.h"

//struct QCmdBase
bool QCmdBase::Decode(CInDataStream & ds)
{
    return QCmdBase::DecodeParam(ds) && DecodeParam(ds);
}

std::string QCmdBase::ToString() const
{
    return std::string("(") + QCmdBase::ToStringHelp() + ToStringHelp() + std::string(")");
}

std::string QCmdBase::ToStringHelp() const
{
    std::ostringstream oss;
    oss<<"(magic_=0x"<<std::hex<<magic_<<",version_="<<std::dec<<U32(version_)<<","<<
        CommandName(cmdtype_)<<",sequence_="<<sequence_<<",length_="<<length_<<")";
    return oss.str();
}

bool QCmdBase::DecodeParam(CInDataStream & ds)
{
    LOCAL_LOGGER(logger,"QCmdBase::DecodeParam");
    ds>>magic_>>version_>>cmdtype_>>sequence_>>length_;
    DEBUG(QCmdBase::ToStringHelp());
    return magic_ == XBASE_PROTOCOL_MAGIC && version_ <= XBASE_PROTOCOL_VERSION && !!ds;
}

//struct RCmdBase
RCmdBase::RCmdBase(U16 cmdtype)
    : version_(XBASE_PROTOCOL_VERSION)
    , cmdtype_(cmdtype)
    , sequence_(0)
{}

RCmdBase::RCmdBase(U16 cmdtype,const QCmdBase & qhead)
    : version_(qhead.version_)
    , cmdtype_(cmdtype)
    , sequence_(qhead.sequence_)
{}

void RCmdBase::Encode(COutDataStream & ds) const
{
    U32 start = U32(ds.Size());
    RCmdBase::EncodeParam(ds);
    EncodeParam(ds);
    U32 len = U32(ds.Size()) - start;
    ds.SetValue(start + HEAD_LEN - 4,len - HEAD_LEN);
}

std::string RCmdBase::ToString() const
{
    return std::string("(") + RCmdBase::ToStringHelp() + ToStringHelp() + std::string(")");
}

std::string RCmdBase::ToStringHelp() const
{
    std::ostringstream oss;
    oss<<"(version_="<<U32(version_)<<","<<CommandName(cmdtype_)
        <<",sequence_="<<sequence_<<")";
    return oss.str();
}

void RCmdBase::EncodeParam(COutDataStream & ds) const
{
    LOCAL_LOGGER(logger,"RCmdBase::EncodeParam");
    DEBUG(RCmdBase::ToStringHelp());
    ds<<U16(XBASE_PROTOCOL_MAGIC)<<version_<<cmdtype_<<sequence_<<U32(0);
}

